package com.mayikt.pay.callback.template;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.mayikt.pay.mapper.PaymentTransactionLogMapper;
import com.mayikt.pay.mapper.entity.PaymentTransactionLog;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 使用模板方法重构异步回调代码
 */
@Slf4j
public abstract class AbstractPayCallbackTemplate {
    private ReentrantLock lock = new ReentrantLock(false);
    @Autowired
    private PaymentTransactionLogMapper paymentTransactionLogMapper;

    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
    /**
     * 获取所有回调参数并验证是否被篡改
     *
     * @param req
     * @param res
     * @return
     */
    public abstract Map<String, String> verifySignature(HttpServletRequest req, HttpServletResponse res);

    /**
     * 错误信息
     *
     * @return
     */
    public abstract String failResult();

    /**
     * 成功信息
     * @return
     */
    public abstract String successResult();

    public abstract String asyncService(Map<String,String> map);

    //    1.将报文放到es  一般使用aop自动实现
    //    2.验证回调报文参数
    //    3.存储日志
    //    4.执行异步回调业务逻辑
    @Transactional(rollbackFor = Exception.class)
    public String asyncCallback(HttpServletRequest req, HttpServletResponse res) {
        //2.验证报文回调参数
        Map<String, String> verifySignature = verifySignature(req, res);
        //3.存储日志
        String paymentId = verifySignature.get("paymentId");
        if (StrUtil.isEmpty(paymentId)) {
            return failResult();
        }
        threadPoolTaskExecutor.execute(new PayLogThread(paymentId,verifySignature));
//        payLog(paymentId, verifySignature);
        String verifyResult = verifySignature.get("verifyResult");
        if (verifyResult.equals("201")) {
            return failResult();
        }
        //4.执行异步回调业务逻辑

        return asyncService(verifySignature);
    }

    /**
     * /3.存储日志
     *
     * @param paymentId
     * @param verifySignature
     */
    public void payLog(String paymentId, Map<String,String> verifySignature) {
        lock.lock();
        PaymentTransactionLog paymentTransactionLog = new PaymentTransactionLog();
        paymentTransactionLog.setTransactionId(paymentId);
        paymentTransactionLog.setAsyncLog(verifySignature.toString());
        int row = paymentTransactionLogMapper.insert(paymentTransactionLog);
        log.info(">>paymentId:{paymentId},verifySignature:{}", JSONObject.toJSONString(verifySignature));
        lock.unlock();
    }

    class PayLogThread implements Runnable{
        private String paymentId;
        private Map<String,String> verifySignature;
        public PayLogThread(String paymentId, Map<String,String> verifySignature){
            this.paymentId = paymentId;
            this.verifySignature = verifySignature;
        }
        @Override
        public void run() {
            payLog(this.paymentId,this.verifySignature);
        }
    }
}
